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