1457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique/* ----------------------------------------------------------------------- 2457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique ffi.c - Copyright (c) 1998, 2007, 2008, 2012 Red Hat, Inc. 3457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique Copyright (c) 2000 Hewlett Packard Company 4457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique Copyright (c) 2011 Anthony Green 5457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 6457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique IA64 Foreign Function Interface 7457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 8457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique Permission is hereby granted, free of charge, to any person obtaining 9457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique a copy of this software and associated documentation files (the 10457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique ``Software''), to deal in the Software without restriction, including 11457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique without limitation the rights to use, copy, modify, merge, publish, 12457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique distribute, sublicense, and/or sell copies of the Software, and to 13457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique permit persons to whom the Software is furnished to do so, subject to 14457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique the following conditions: 15457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 16457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique The above copyright notice and this permission notice shall be included 17457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique in all copies or substantial portions of the Software. 18457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 19457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, 20457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 23457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 24457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 26457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique DEALINGS IN THE SOFTWARE. 27457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique ----------------------------------------------------------------------- */ 28457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 29457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#include <ffi.h> 30457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#include <ffi_common.h> 31457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 32457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#include <stdlib.h> 33457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#include <stdbool.h> 34457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#include <float.h> 35457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 36457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#include "ia64_flags.h" 37457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 38457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique/* A 64-bit pointer value. In LP64 mode, this is effectively a plain 39457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique pointer. In ILP32 mode, it's a pointer that's been extended to 40457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 64 bits by "addp4". */ 41457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquetypedef void *PTR64 __attribute__((mode(DI))); 42457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 43457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique/* Memory image of fp register contents. This is the implementation 44457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique specific format used by ldf.fill/stf.spill. All we care about is 45457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique that it wants a 16 byte aligned slot. */ 46457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquetypedef struct 47457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique{ 48457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique UINT64 x[2] __attribute__((aligned(16))); 49457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique} fpreg; 50457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 51457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 52457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique/* The stack layout given to ffi_call_unix and ffi_closure_unix_inner. */ 53457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 54457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquestruct ia64_args 55457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique{ 56457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique fpreg fp_regs[8]; /* Contents of 8 fp arg registers. */ 57457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique UINT64 gp_regs[8]; /* Contents of 8 gp arg registers. */ 58457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique UINT64 other_args[]; /* Arguments passed on stack, variable size. */ 59457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique}; 60457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 61457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 62457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique/* Adjust ADDR, a pointer to an 8 byte slot, to point to the low LEN bytes. */ 63457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 64457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquestatic inline void * 65457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piqueendian_adjust (void *addr, size_t len) 66457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique{ 67457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#ifdef __BIG_ENDIAN__ 68457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique return addr + (8 - len); 69457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#else 70457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique return addr; 71457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#endif 72457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique} 73457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 74457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique/* Store VALUE to ADDR in the current cpu implementation's fp spill format. 75457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique This is a macro instead of a function, so that it works for all 3 floating 76457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique point types without type conversions. Type conversion to long double breaks 77457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique the denorm support. */ 78457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 79457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#define stf_spill(addr, value) \ 80457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique asm ("stf.spill %0 = %1%P0" : "=m" (*addr) : "f"(value)); 81457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 82457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique/* Load a value from ADDR, which is in the current cpu implementation's 83457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique fp spill format. As above, this must also be a macro. */ 84457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 85457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#define ldf_fill(result, addr) \ 86457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique asm ("ldf.fill %0 = %1%P1" : "=f"(result) : "m"(*addr)); 87457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 88457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique/* Return the size of the C type associated with with TYPE. Which will 89457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique be one of the FFI_IA64_TYPE_HFA_* values. */ 90457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 91457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquestatic size_t 92457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquehfa_type_size (int type) 93457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique{ 94457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique switch (type) 95457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 96457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_IA64_TYPE_HFA_FLOAT: 97457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique return sizeof(float); 98457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_IA64_TYPE_HFA_DOUBLE: 99457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique return sizeof(double); 100457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_IA64_TYPE_HFA_LDOUBLE: 101457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique return sizeof(__float80); 102457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique default: 103457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique abort (); 104457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 105457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique} 106457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 107457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique/* Load from ADDR a value indicated by TYPE. Which will be one of 108457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique the FFI_IA64_TYPE_HFA_* values. */ 109457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 110457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquestatic void 111457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquehfa_type_load (fpreg *fpaddr, int type, void *addr) 112457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique{ 113457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique switch (type) 114457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 115457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_IA64_TYPE_HFA_FLOAT: 116457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique stf_spill (fpaddr, *(float *) addr); 117457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique return; 118457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_IA64_TYPE_HFA_DOUBLE: 119457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique stf_spill (fpaddr, *(double *) addr); 120457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique return; 121457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_IA64_TYPE_HFA_LDOUBLE: 122457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique stf_spill (fpaddr, *(__float80 *) addr); 123457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique return; 124457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique default: 125457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique abort (); 126457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 127457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique} 128457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 129457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique/* Load VALUE into ADDR as indicated by TYPE. Which will be one of 130457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique the FFI_IA64_TYPE_HFA_* values. */ 131457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 132457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquestatic void 133457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquehfa_type_store (int type, void *addr, fpreg *fpaddr) 134457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique{ 135457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique switch (type) 136457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 137457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_IA64_TYPE_HFA_FLOAT: 138457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 139457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique float result; 140457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique ldf_fill (result, fpaddr); 141457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique *(float *) addr = result; 142457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique break; 143457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 144457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_IA64_TYPE_HFA_DOUBLE: 145457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 146457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique double result; 147457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique ldf_fill (result, fpaddr); 148457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique *(double *) addr = result; 149457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique break; 150457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 151457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_IA64_TYPE_HFA_LDOUBLE: 152457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 153457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique __float80 result; 154457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique ldf_fill (result, fpaddr); 155457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique *(__float80 *) addr = result; 156457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique break; 157457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 158457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique default: 159457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique abort (); 160457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 161457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique} 162457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 163457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique/* Is TYPE a struct containing floats, doubles, or extended doubles, 164457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique all of the same fp type? If so, return the element type. Return 165457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique FFI_TYPE_VOID if not. */ 166457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 167457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquestatic int 168457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquehfa_element_type (ffi_type *type, int nested) 169457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique{ 170457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique int element = FFI_TYPE_VOID; 171457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 172457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique switch (type->type) 173457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 174457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_FLOAT: 175457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique /* We want to return VOID for raw floating-point types, but the 176457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique synthetic HFA type if we're nested within an aggregate. */ 177457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique if (nested) 178457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique element = FFI_IA64_TYPE_HFA_FLOAT; 179457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique break; 180457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 181457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_DOUBLE: 182457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique /* Similarly. */ 183457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique if (nested) 184457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique element = FFI_IA64_TYPE_HFA_DOUBLE; 185457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique break; 186457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 187457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_LONGDOUBLE: 188457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique /* Similarly, except that that HFA is true for double extended, 189457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique but not quad precision. Both have sizeof == 16, so tell the 190457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique difference based on the precision. */ 191457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique if (LDBL_MANT_DIG == 64 && nested) 192457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique element = FFI_IA64_TYPE_HFA_LDOUBLE; 193457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique break; 194457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 195457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_STRUCT: 196457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 197457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique ffi_type **ptr = &type->elements[0]; 198457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 199457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique for (ptr = &type->elements[0]; *ptr ; ptr++) 200457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 201457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique int sub_element = hfa_element_type (*ptr, 1); 202457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique if (sub_element == FFI_TYPE_VOID) 203457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique return FFI_TYPE_VOID; 204457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 205457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique if (element == FFI_TYPE_VOID) 206457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique element = sub_element; 207457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique else if (element != sub_element) 208457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique return FFI_TYPE_VOID; 209457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 210457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 211457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique break; 212457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 213457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique default: 214457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique return FFI_TYPE_VOID; 215457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 216457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 217457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique return element; 218457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique} 219457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 220457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 221457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique/* Perform machine dependent cif processing. */ 222457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 223457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piqueffi_status 224457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piqueffi_prep_cif_machdep(ffi_cif *cif) 225457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique{ 226457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique int flags; 227457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 228457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique /* Adjust cif->bytes to include space for the bits of the ia64_args frame 229457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique that precedes the integer register portion. The estimate that the 230457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique generic bits did for the argument space required is good enough for the 231457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique integer component. */ 232457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique cif->bytes += offsetof(struct ia64_args, gp_regs[0]); 233457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique if (cif->bytes < sizeof(struct ia64_args)) 234457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique cif->bytes = sizeof(struct ia64_args); 235457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 236457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique /* Set the return type flag. */ 237457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique flags = cif->rtype->type; 238457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique switch (cif->rtype->type) 239457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 240457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_LONGDOUBLE: 241457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique /* Leave FFI_TYPE_LONGDOUBLE as meaning double extended precision, 242457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique and encode quad precision as a two-word integer structure. */ 243457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique if (LDBL_MANT_DIG != 64) 244457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique flags = FFI_IA64_TYPE_SMALL_STRUCT | (16 << 8); 245457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique break; 246457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 247457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_STRUCT: 248457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 249457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique size_t size = cif->rtype->size; 250457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique int hfa_type = hfa_element_type (cif->rtype, 0); 251457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 252457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique if (hfa_type != FFI_TYPE_VOID) 253457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 254457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique size_t nelts = size / hfa_type_size (hfa_type); 255457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique if (nelts <= 8) 256457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique flags = hfa_type | (size << 8); 257457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 258457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique else 259457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 260457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique if (size <= 32) 261457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique flags = FFI_IA64_TYPE_SMALL_STRUCT | (size << 8); 262457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 263457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 264457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique break; 265457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 266457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique default: 267457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique break; 268457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 269457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique cif->flags = flags; 270457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 271457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique return FFI_OK; 272457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique} 273457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 274457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piqueextern int ffi_call_unix (struct ia64_args *, PTR64, void (*)(void), UINT64); 275457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 276457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquevoid 277457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piqueffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) 278457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique{ 279457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique struct ia64_args *stack; 280457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique long i, avn, gpcount, fpcount; 281457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique ffi_type **p_arg; 282457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 283457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique FFI_ASSERT (cif->abi == FFI_UNIX); 284457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 285457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique /* If we have no spot for a return value, make one. */ 286457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique if (rvalue == NULL && cif->rtype->type != FFI_TYPE_VOID) 287457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique rvalue = alloca (cif->rtype->size); 288457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 289457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique /* Allocate the stack frame. */ 290457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique stack = alloca (cif->bytes); 291457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 292457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique gpcount = fpcount = 0; 293457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique avn = cif->nargs; 294457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique for (i = 0, p_arg = cif->arg_types; i < avn; i++, p_arg++) 295457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 296457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique switch ((*p_arg)->type) 297457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 298457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_SINT8: 299457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique stack->gp_regs[gpcount++] = *(SINT8 *)avalue[i]; 300457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique break; 301457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_UINT8: 302457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique stack->gp_regs[gpcount++] = *(UINT8 *)avalue[i]; 303457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique break; 304457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_SINT16: 305457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique stack->gp_regs[gpcount++] = *(SINT16 *)avalue[i]; 306457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique break; 307457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_UINT16: 308457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique stack->gp_regs[gpcount++] = *(UINT16 *)avalue[i]; 309457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique break; 310457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_SINT32: 311457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique stack->gp_regs[gpcount++] = *(SINT32 *)avalue[i]; 312457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique break; 313457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_UINT32: 314457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique stack->gp_regs[gpcount++] = *(UINT32 *)avalue[i]; 315457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique break; 316457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_SINT64: 317457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_UINT64: 318457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique stack->gp_regs[gpcount++] = *(UINT64 *)avalue[i]; 319457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique break; 320457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 321457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_POINTER: 322457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique stack->gp_regs[gpcount++] = (UINT64)(PTR64) *(void **)avalue[i]; 323457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique break; 324457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 325457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_FLOAT: 326457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique if (gpcount < 8 && fpcount < 8) 327457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique stf_spill (&stack->fp_regs[fpcount++], *(float *)avalue[i]); 328457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 329457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique UINT32 tmp; 330457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique memcpy (&tmp, avalue[i], sizeof (UINT32)); 331457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique stack->gp_regs[gpcount++] = tmp; 332457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 333457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique break; 334457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 335457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_DOUBLE: 336457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique if (gpcount < 8 && fpcount < 8) 337457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique stf_spill (&stack->fp_regs[fpcount++], *(double *)avalue[i]); 338457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique memcpy (&stack->gp_regs[gpcount++], avalue[i], sizeof (UINT64)); 339457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique break; 340457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 341457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_LONGDOUBLE: 342457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique if (gpcount & 1) 343457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique gpcount++; 344457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique if (LDBL_MANT_DIG == 64 && gpcount < 8 && fpcount < 8) 345457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique stf_spill (&stack->fp_regs[fpcount++], *(__float80 *)avalue[i]); 346457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique memcpy (&stack->gp_regs[gpcount], avalue[i], 16); 347457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique gpcount += 2; 348457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique break; 349457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 350457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_STRUCT: 351457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 352457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique size_t size = (*p_arg)->size; 353457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique size_t align = (*p_arg)->alignment; 354457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique int hfa_type = hfa_element_type (*p_arg, 0); 355457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 356457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique FFI_ASSERT (align <= 16); 357457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique if (align == 16 && (gpcount & 1)) 358457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique gpcount++; 359457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 360457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique if (hfa_type != FFI_TYPE_VOID) 361457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 362457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique size_t hfa_size = hfa_type_size (hfa_type); 363457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique size_t offset = 0; 364457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique size_t gp_offset = gpcount * 8; 365457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 366457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique while (fpcount < 8 367457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique && offset < size 368457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique && gp_offset < 8 * 8) 369457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 370457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique hfa_type_load (&stack->fp_regs[fpcount], hfa_type, 371457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique avalue[i] + offset); 372457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique offset += hfa_size; 373457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique gp_offset += hfa_size; 374457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique fpcount += 1; 375457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 376457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 377457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 378457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique memcpy (&stack->gp_regs[gpcount], avalue[i], size); 379457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique gpcount += (size + 7) / 8; 380457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 381457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique break; 382457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 383457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique default: 384457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique abort (); 385457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 386457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 387457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 388457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique ffi_call_unix (stack, rvalue, fn, cif->flags); 389457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique} 390457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 391457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique/* Closures represent a pair consisting of a function pointer, and 392457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique some user data. A closure is invoked by reinterpreting the closure 393457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique as a function pointer, and branching to it. Thus we can make an 394457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique interpreted function callable as a C function: We turn the 395457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique interpreter itself, together with a pointer specifying the 396457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique interpreted procedure, into a closure. 397457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 398457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique For IA64, function pointer are already pairs consisting of a code 399457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique pointer, and a gp pointer. The latter is needed to access global 400457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique variables. Here we set up such a pair as the first two words of 401457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique the closure (in the "trampoline" area), but we replace the gp 402457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique pointer with a pointer to the closure itself. We also add the real 403457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique gp pointer to the closure. This allows the function entry code to 404457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique both retrieve the user data, and to restore the correct gp pointer. */ 405457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 406457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piqueextern void ffi_closure_unix (); 407457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 408457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piqueffi_status 409457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piqueffi_prep_closure_loc (ffi_closure* closure, 410457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique ffi_cif* cif, 411457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique void (*fun)(ffi_cif*,void*,void**,void*), 412457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique void *user_data, 413457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique void *codeloc) 414457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique{ 415457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique /* The layout of a function descriptor. A C function pointer really 416457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique points to one of these. */ 417457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique struct ia64_fd 418457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 419457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique UINT64 code_pointer; 420457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique UINT64 gp; 421457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique }; 422457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 423457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique struct ffi_ia64_trampoline_struct 424457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 425457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique UINT64 code_pointer; /* Pointer to ffi_closure_unix. */ 426457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique UINT64 fake_gp; /* Pointer to closure, installed as gp. */ 427457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique UINT64 real_gp; /* Real gp value. */ 428457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique }; 429457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 430457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique struct ffi_ia64_trampoline_struct *tramp; 431457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique struct ia64_fd *fd; 432457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 433457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique if (cif->abi != FFI_UNIX) 434457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique return FFI_BAD_ABI; 435457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 436457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique tramp = (struct ffi_ia64_trampoline_struct *)closure->tramp; 437457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique fd = (struct ia64_fd *)(void *)ffi_closure_unix; 438457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 439457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique tramp->code_pointer = fd->code_pointer; 440457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique tramp->real_gp = fd->gp; 441457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique tramp->fake_gp = (UINT64)(PTR64)codeloc; 442457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique closure->cif = cif; 443457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique closure->user_data = user_data; 444457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique closure->fun = fun; 445457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 446457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique return FFI_OK; 447457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique} 448457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 449457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 450457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd PiqueUINT64 451457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piqueffi_closure_unix_inner (ffi_closure *closure, struct ia64_args *stack, 452457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique void *rvalue, void *r8) 453457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique{ 454457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique ffi_cif *cif; 455457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique void **avalue; 456457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique ffi_type **p_arg; 457457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique long i, avn, gpcount, fpcount; 458457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 459457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique cif = closure->cif; 460457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique avn = cif->nargs; 461457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique avalue = alloca (avn * sizeof (void *)); 462457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 463457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique /* If the structure return value is passed in memory get that location 464457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique from r8 so as to pass the value directly back to the caller. */ 465457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique if (cif->flags == FFI_TYPE_STRUCT) 466457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique rvalue = r8; 467457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 468457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique gpcount = fpcount = 0; 469457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique for (i = 0, p_arg = cif->arg_types; i < avn; i++, p_arg++) 470457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 471457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique switch ((*p_arg)->type) 472457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 473457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_SINT8: 474457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_UINT8: 475457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique avalue[i] = endian_adjust(&stack->gp_regs[gpcount++], 1); 476457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique break; 477457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_SINT16: 478457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_UINT16: 479457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique avalue[i] = endian_adjust(&stack->gp_regs[gpcount++], 2); 480457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique break; 481457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_SINT32: 482457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_UINT32: 483457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique avalue[i] = endian_adjust(&stack->gp_regs[gpcount++], 4); 484457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique break; 485457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_SINT64: 486457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_UINT64: 487457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique avalue[i] = &stack->gp_regs[gpcount++]; 488457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique break; 489457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_POINTER: 490457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique avalue[i] = endian_adjust(&stack->gp_regs[gpcount++], sizeof(void*)); 491457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique break; 492457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 493457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_FLOAT: 494457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique if (gpcount < 8 && fpcount < 8) 495457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 496457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique fpreg *addr = &stack->fp_regs[fpcount++]; 497457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique float result; 498457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique avalue[i] = addr; 499457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique ldf_fill (result, addr); 500457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique *(float *)addr = result; 501457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 502457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique else 503457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique avalue[i] = endian_adjust(&stack->gp_regs[gpcount], 4); 504457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique gpcount++; 505457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique break; 506457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 507457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_DOUBLE: 508457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique if (gpcount < 8 && fpcount < 8) 509457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 510457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique fpreg *addr = &stack->fp_regs[fpcount++]; 511457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique double result; 512457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique avalue[i] = addr; 513457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique ldf_fill (result, addr); 514457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique *(double *)addr = result; 515457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 516457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique else 517457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique avalue[i] = &stack->gp_regs[gpcount]; 518457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique gpcount++; 519457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique break; 520457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 521457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_LONGDOUBLE: 522457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique if (gpcount & 1) 523457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique gpcount++; 524457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique if (LDBL_MANT_DIG == 64 && gpcount < 8 && fpcount < 8) 525457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 526457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique fpreg *addr = &stack->fp_regs[fpcount++]; 527457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique __float80 result; 528457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique avalue[i] = addr; 529457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique ldf_fill (result, addr); 530457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique *(__float80 *)addr = result; 531457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 532457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique else 533457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique avalue[i] = &stack->gp_regs[gpcount]; 534457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique gpcount += 2; 535457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique break; 536457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 537457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_STRUCT: 538457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 539457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique size_t size = (*p_arg)->size; 540457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique size_t align = (*p_arg)->alignment; 541457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique int hfa_type = hfa_element_type (*p_arg, 0); 542457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 543457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique FFI_ASSERT (align <= 16); 544457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique if (align == 16 && (gpcount & 1)) 545457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique gpcount++; 546457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 547457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique if (hfa_type != FFI_TYPE_VOID) 548457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 549457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique size_t hfa_size = hfa_type_size (hfa_type); 550457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique size_t offset = 0; 551457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique size_t gp_offset = gpcount * 8; 552457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique void *addr = alloca (size); 553457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 554457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique avalue[i] = addr; 555457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 556457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique while (fpcount < 8 557457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique && offset < size 558457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique && gp_offset < 8 * 8) 559457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 560457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique hfa_type_store (hfa_type, addr + offset, 561457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique &stack->fp_regs[fpcount]); 562457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique offset += hfa_size; 563457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique gp_offset += hfa_size; 564457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique fpcount += 1; 565457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 566457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 567457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique if (offset < size) 568457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique memcpy (addr + offset, (char *)stack->gp_regs + gp_offset, 569457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique size - offset); 570457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 571457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique else 572457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique avalue[i] = &stack->gp_regs[gpcount]; 573457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 574457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique gpcount += (size + 7) / 8; 575457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 576457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique break; 577457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 578457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique default: 579457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique abort (); 580457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 581457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 582457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 583457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique closure->fun (cif, rvalue, avalue, closure->user_data); 584457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 585457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique return cif->flags; 586457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique} 587