1457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique/* Copyright (c) 2009, 2010, 2011, 2012 ARM Ltd. 2457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 3457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd PiquePermission is hereby granted, free of charge, to any person obtaining 4457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquea copy of this software and associated documentation files (the 5457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique``Software''), to deal in the Software without restriction, including 6457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquewithout limitation the rights to use, copy, modify, merge, publish, 7457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquedistribute, sublicense, and/or sell copies of the Software, and to 8457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquepermit persons to whom the Software is furnished to do so, subject to 9457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquethe following conditions: 10457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 11457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd PiqueThe above copyright notice and this permission notice shall be 12457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piqueincluded in all copies or substantial portions of the Software. 13457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 14457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd PiqueTHE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, 15457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd PiqueEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd PiqueMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 17457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd PiqueIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 18457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd PiqueCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 19457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd PiqueTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 20457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd PiqueSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ 21457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 22457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#include <stdio.h> 23457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 24457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#include <ffi.h> 25457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#include <ffi_common.h> 26457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 27457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#include <stdlib.h> 28457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 29457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique/* Stack alignment requirement in bytes */ 30457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#if defined (__APPLE__) 31457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#define AARCH64_STACK_ALIGN 1 32457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#else 33457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#define AARCH64_STACK_ALIGN 16 34457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#endif 35457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 36457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#define N_X_ARG_REG 8 37457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#define N_V_ARG_REG 8 38457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 39457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#define AARCH64_FFI_WITH_V (1 << AARCH64_FFI_WITH_V_BIT) 40457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 41457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piqueunion _d 42457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique{ 43457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique UINT64 d; 44457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique UINT32 s[2]; 45457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique}; 46457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 47457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquestruct call_context 48457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique{ 49457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique UINT64 x [AARCH64_N_XREG]; 50457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique struct 51457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 52457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique union _d d[2]; 53457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } v [AARCH64_N_VREG]; 54457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique}; 55457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 56457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#if defined (__clang__) && defined (__APPLE__) 57457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piqueextern void 58457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquesys_icache_invalidate (void *start, size_t len); 59457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#endif 60457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 61457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquestatic inline void 62457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piqueffi_clear_cache (void *start, void *end) 63457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique{ 64457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#if defined (__clang__) && defined (__APPLE__) 65457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique sys_icache_invalidate (start, (char *)end - (char *)start); 66457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#elif defined (__GNUC__) 67457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique __builtin___clear_cache (start, end); 68457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#else 69457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#error "Missing builtin to flush instruction cache" 70457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#endif 71457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique} 72457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 73457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquestatic void * 74457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piqueget_x_addr (struct call_context *context, unsigned n) 75457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique{ 76457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique return &context->x[n]; 77457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique} 78457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 79457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquestatic void * 80457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piqueget_s_addr (struct call_context *context, unsigned n) 81457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique{ 82457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#if defined __AARCH64EB__ 83457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique return &context->v[n].d[1].s[1]; 84457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#else 85457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique return &context->v[n].d[0].s[0]; 86457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#endif 87457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique} 88457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 89457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquestatic void * 90457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piqueget_d_addr (struct call_context *context, unsigned n) 91457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique{ 92457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#if defined __AARCH64EB__ 93457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique return &context->v[n].d[1]; 94457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#else 95457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique return &context->v[n].d[0]; 96457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#endif 97457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique} 98457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 99457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquestatic void * 100457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piqueget_v_addr (struct call_context *context, unsigned n) 101457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique{ 102457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique return &context->v[n]; 103457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique} 104457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 105457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique/* Return the memory location at which a basic type would reside 106457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique were it to have been stored in register n. */ 107457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 108457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquestatic void * 109457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piqueget_basic_type_addr (unsigned short type, struct call_context *context, 110457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique unsigned n) 111457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique{ 112457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique switch (type) 113457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 114457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_FLOAT: 115457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique return get_s_addr (context, n); 116457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_DOUBLE: 117457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique return get_d_addr (context, n); 118457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#if FFI_TYPE_DOUBLE != FFI_TYPE_LONGDOUBLE 119457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_LONGDOUBLE: 120457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique return get_v_addr (context, n); 121457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#endif 122457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_UINT8: 123457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_SINT8: 124457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_UINT16: 125457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_SINT16: 126457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_UINT32: 127457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_SINT32: 128457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_INT: 129457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_POINTER: 130457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_UINT64: 131457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_SINT64: 132457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique return get_x_addr (context, n); 133457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_VOID: 134457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique return NULL; 135457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique default: 136457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique FFI_ASSERT (0); 137457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique return NULL; 138457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 139457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique} 140457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 141457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique/* Return the alignment width for each of the basic types. */ 142457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 143457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquestatic size_t 144457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piqueget_basic_type_alignment (unsigned short type) 145457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique{ 146457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique switch (type) 147457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 148457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_FLOAT: 149457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#if defined (__APPLE__) 150457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique return sizeof (UINT32); 151457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#endif 152457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_DOUBLE: 153457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique return sizeof (UINT64); 154457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#if FFI_TYPE_DOUBLE != FFI_TYPE_LONGDOUBLE 155457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_LONGDOUBLE: 156457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique return sizeof (long double); 157457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#endif 158457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_UINT8: 159457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_SINT8: 160457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#if defined (__APPLE__) 161457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique return sizeof (UINT8); 162457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#endif 163457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_UINT16: 164457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_SINT16: 165457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#if defined (__APPLE__) 166457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique return sizeof (UINT16); 167457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#endif 168457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_UINT32: 169457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_INT: 170457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_SINT32: 171457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#if defined (__APPLE__) 172457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique return sizeof (UINT32); 173457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#endif 174457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_POINTER: 175457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_UINT64: 176457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_SINT64: 177457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique return sizeof (UINT64); 178457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 179457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique default: 180457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique FFI_ASSERT (0); 181457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique return 0; 182457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 183457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique} 184457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 185457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique/* Return the size in bytes for each of the basic types. */ 186457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 187457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquestatic size_t 188457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piqueget_basic_type_size (unsigned short type) 189457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique{ 190457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique switch (type) 191457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 192457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_FLOAT: 193457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique return sizeof (UINT32); 194457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_DOUBLE: 195457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique return sizeof (UINT64); 196457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#if FFI_TYPE_DOUBLE != FFI_TYPE_LONGDOUBLE 197457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_LONGDOUBLE: 198457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique return sizeof (long double); 199457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#endif 200457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_UINT8: 201457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique return sizeof (UINT8); 202457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_SINT8: 203457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique return sizeof (SINT8); 204457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_UINT16: 205457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique return sizeof (UINT16); 206457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_SINT16: 207457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique return sizeof (SINT16); 208457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_UINT32: 209457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique return sizeof (UINT32); 210457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_INT: 211457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_SINT32: 212457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique return sizeof (SINT32); 213457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_POINTER: 214457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_UINT64: 215457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique return sizeof (UINT64); 216457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_SINT64: 217457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique return sizeof (SINT64); 218457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 219457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique default: 220457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique FFI_ASSERT (0); 221457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique return 0; 222457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 223457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique} 224457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 225457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piqueextern void 226457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piqueffi_call_SYSV (unsigned (*)(struct call_context *context, unsigned char *, 227457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique extended_cif *), 228457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique struct call_context *context, 229457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique extended_cif *, 230457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique size_t, 231457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique void (*fn)(void)); 232457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 233457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piqueextern void 234457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piqueffi_closure_SYSV (ffi_closure *); 235457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 236457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique/* Test for an FFI floating point representation. */ 237457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 238457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquestatic unsigned 239457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piqueis_floating_type (unsigned short type) 240457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique{ 241457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique return (type == FFI_TYPE_FLOAT || type == FFI_TYPE_DOUBLE 242457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique || type == FFI_TYPE_LONGDOUBLE); 243457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique} 244457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 245457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique/* Test for a homogeneous structure. */ 246457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 247457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquestatic unsigned short 248457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piqueget_homogeneous_type (ffi_type *ty) 249457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique{ 250457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique if (ty->type == FFI_TYPE_STRUCT && ty->elements) 251457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 252457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique unsigned i; 253457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique unsigned short candidate_type 254457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique = get_homogeneous_type (ty->elements[0]); 255457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique for (i =1; ty->elements[i]; i++) 256457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 257457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique unsigned short iteration_type = 0; 258457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique /* If we have a nested struct, we must find its homogeneous type. 259457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique If that fits with our candidate type, we are still 260457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique homogeneous. */ 261457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique if (ty->elements[i]->type == FFI_TYPE_STRUCT 262457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique && ty->elements[i]->elements) 263457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 264457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique iteration_type = get_homogeneous_type (ty->elements[i]); 265457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 266457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique else 267457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 268457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique iteration_type = ty->elements[i]->type; 269457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 270457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 271457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique /* If we are not homogeneous, return FFI_TYPE_STRUCT. */ 272457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique if (candidate_type != iteration_type) 273457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique return FFI_TYPE_STRUCT; 274457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 275457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique return candidate_type; 276457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 277457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 278457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique /* Base case, we have no more levels of nesting, so we 279457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique are a basic type, and so, trivially homogeneous in that type. */ 280457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique return ty->type; 281457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique} 282457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 283457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique/* Determine the number of elements within a STRUCT. 284457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 285457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique Note, we must handle nested structs. 286457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 287457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique If ty is not a STRUCT this function will return 0. */ 288457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 289457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquestatic unsigned 290457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piqueelement_count (ffi_type *ty) 291457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique{ 292457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique if (ty->type == FFI_TYPE_STRUCT && ty->elements) 293457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 294457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique unsigned n; 295457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique unsigned elems = 0; 296457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique for (n = 0; ty->elements[n]; n++) 297457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 298457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique if (ty->elements[n]->type == FFI_TYPE_STRUCT 299457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique && ty->elements[n]->elements) 300457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique elems += element_count (ty->elements[n]); 301457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique else 302457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique elems++; 303457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 304457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique return elems; 305457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 306457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique return 0; 307457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique} 308457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 309457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique/* Test for a homogeneous floating point aggregate. 310457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 311457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique A homogeneous floating point aggregate is a homogeneous aggregate of 312457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique a half- single- or double- precision floating point type with one 313457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique to four elements. Note that this includes nested structs of the 314457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique basic type. */ 315457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 316457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquestatic int 317457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piqueis_hfa (ffi_type *ty) 318457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique{ 319457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique if (ty->type == FFI_TYPE_STRUCT 320457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique && ty->elements[0] 321457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique && is_floating_type (get_homogeneous_type (ty))) 322457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 323457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique unsigned n = element_count (ty); 324457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique return n >= 1 && n <= 4; 325457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 326457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique return 0; 327457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique} 328457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 329457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique/* Test if an ffi_type is a candidate for passing in a register. 330457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 331457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique This test does not check that sufficient registers of the 332457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique appropriate class are actually available, merely that IFF 333457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique sufficient registers are available then the argument will be passed 334457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique in register(s). 335457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 336457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique Note that an ffi_type that is deemed to be a register candidate 337457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique will always be returned in registers. 338457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 339457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique Returns 1 if a register candidate else 0. */ 340457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 341457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquestatic int 342457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piqueis_register_candidate (ffi_type *ty) 343457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique{ 344457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique switch (ty->type) 345457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 346457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_VOID: 347457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_FLOAT: 348457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_DOUBLE: 349457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#if FFI_TYPE_DOUBLE != FFI_TYPE_LONGDOUBLE 350457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_LONGDOUBLE: 351457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#endif 352457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_UINT8: 353457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_UINT16: 354457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_UINT32: 355457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_UINT64: 356457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_POINTER: 357457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_SINT8: 358457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_SINT16: 359457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_SINT32: 360457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_INT: 361457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_SINT64: 362457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique return 1; 363457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 364457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_STRUCT: 365457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique if (is_hfa (ty)) 366457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 367457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique return 1; 368457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 369457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique else if (ty->size > 16) 370457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 371457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique /* Too large. Will be replaced with a pointer to memory. The 372457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique pointer MAY be passed in a register, but the value will 373457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique not. This test specifically fails since the argument will 374457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique never be passed by value in registers. */ 375457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique return 0; 376457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 377457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique else 378457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 379457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique /* Might be passed in registers depending on the number of 380457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique registers required. */ 381457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique return (ty->size + 7) / 8 < N_X_ARG_REG; 382457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 383457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique break; 384457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 385457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique default: 386457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique FFI_ASSERT (0); 387457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique break; 388457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 389457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 390457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique return 0; 391457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique} 392457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 393457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique/* Test if an ffi_type argument or result is a candidate for a vector 394457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique register. */ 395457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 396457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquestatic int 397457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piqueis_v_register_candidate (ffi_type *ty) 398457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique{ 399457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique return is_floating_type (ty->type) 400457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique || (ty->type == FFI_TYPE_STRUCT && is_hfa (ty)); 401457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique} 402457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 403457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique/* Representation of the procedure call argument marshalling 404457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique state. 405457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 406457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique The terse state variable names match the names used in the AARCH64 407457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique PCS. */ 408457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 409457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquestruct arg_state 410457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique{ 411457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique unsigned ngrn; /* Next general-purpose register number. */ 412457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique unsigned nsrn; /* Next vector register number. */ 413457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique size_t nsaa; /* Next stack offset. */ 414457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 415457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#if defined (__APPLE__) 416457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique unsigned allocating_variadic; 417457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#endif 418457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique}; 419457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 420457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique/* Initialize a procedure call argument marshalling state. */ 421457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquestatic void 422457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquearg_init (struct arg_state *state, size_t call_frame_size) 423457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique{ 424457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique state->ngrn = 0; 425457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique state->nsrn = 0; 426457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique state->nsaa = 0; 427457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 428457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#if defined (__APPLE__) 429457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique state->allocating_variadic = 0; 430457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#endif 431457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique} 432457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 433457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique/* Return the number of available consecutive core argument 434457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique registers. */ 435457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 436457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquestatic unsigned 437457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piqueavailable_x (struct arg_state *state) 438457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique{ 439457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique return N_X_ARG_REG - state->ngrn; 440457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique} 441457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 442457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique/* Return the number of available consecutive vector argument 443457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique registers. */ 444457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 445457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquestatic unsigned 446457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piqueavailable_v (struct arg_state *state) 447457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique{ 448457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique return N_V_ARG_REG - state->nsrn; 449457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique} 450457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 451457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquestatic void * 452457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piqueallocate_to_x (struct call_context *context, struct arg_state *state) 453457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique{ 454457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique FFI_ASSERT (state->ngrn < N_X_ARG_REG); 455457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique return get_x_addr (context, (state->ngrn)++); 456457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique} 457457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 458457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquestatic void * 459457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piqueallocate_to_s (struct call_context *context, struct arg_state *state) 460457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique{ 461457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique FFI_ASSERT (state->nsrn < N_V_ARG_REG); 462457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique return get_s_addr (context, (state->nsrn)++); 463457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique} 464457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 465457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquestatic void * 466457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piqueallocate_to_d (struct call_context *context, struct arg_state *state) 467457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique{ 468457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique FFI_ASSERT (state->nsrn < N_V_ARG_REG); 469457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique return get_d_addr (context, (state->nsrn)++); 470457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique} 471457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 472457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquestatic void * 473457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piqueallocate_to_v (struct call_context *context, struct arg_state *state) 474457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique{ 475457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique FFI_ASSERT (state->nsrn < N_V_ARG_REG); 476457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique return get_v_addr (context, (state->nsrn)++); 477457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique} 478457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 479457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique/* Allocate an aligned slot on the stack and return a pointer to it. */ 480457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquestatic void * 481457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piqueallocate_to_stack (struct arg_state *state, void *stack, size_t alignment, 482457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique size_t size) 483457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique{ 484457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique void *allocation; 485457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 486457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique /* Round up the NSAA to the larger of 8 or the natural 487457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique alignment of the argument's type. */ 488457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique state->nsaa = ALIGN (state->nsaa, alignment); 489457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique state->nsaa = ALIGN (state->nsaa, alignment); 490457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#if defined (__APPLE__) 491457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique if (state->allocating_variadic) 492457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique state->nsaa = ALIGN (state->nsaa, 8); 493457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#else 494457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique state->nsaa = ALIGN (state->nsaa, 8); 495457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#endif 496457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 497457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique allocation = stack + state->nsaa; 498457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 499457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique state->nsaa += size; 500457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique return allocation; 501457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique} 502457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 503457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquestatic void 504457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquecopy_basic_type (void *dest, void *source, unsigned short type) 505457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique{ 506457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique /* This is necessary to ensure that basic types are copied 507457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique sign extended to 64-bits as libffi expects. */ 508457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique switch (type) 509457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 510457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_FLOAT: 511457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique *(float *) dest = *(float *) source; 512457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique break; 513457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_DOUBLE: 514457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique *(double *) dest = *(double *) source; 515457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique break; 516457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#if FFI_TYPE_DOUBLE != FFI_TYPE_LONGDOUBLE 517457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_LONGDOUBLE: 518457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique *(long double *) dest = *(long double *) source; 519457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique break; 520457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#endif 521457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_UINT8: 522457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique *(ffi_arg *) dest = *(UINT8 *) source; 523457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique break; 524457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_SINT8: 525457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique *(ffi_sarg *) dest = *(SINT8 *) source; 526457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique break; 527457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_UINT16: 528457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique *(ffi_arg *) dest = *(UINT16 *) source; 529457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique break; 530457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_SINT16: 531457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique *(ffi_sarg *) dest = *(SINT16 *) source; 532457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique break; 533457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_UINT32: 534457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique *(ffi_arg *) dest = *(UINT32 *) source; 535457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique break; 536457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_INT: 537457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_SINT32: 538457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique *(ffi_sarg *) dest = *(SINT32 *) source; 539457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique break; 540457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_POINTER: 541457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_UINT64: 542457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique *(ffi_arg *) dest = *(UINT64 *) source; 543457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique break; 544457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_SINT64: 545457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique *(ffi_sarg *) dest = *(SINT64 *) source; 546457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique break; 547457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_VOID: 548457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique break; 549457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 550457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique default: 551457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique FFI_ASSERT (0); 552457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 553457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique} 554457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 555457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquestatic void 556457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquecopy_hfa_to_reg_or_stack (void *memory, 557457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique ffi_type *ty, 558457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique struct call_context *context, 559457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique unsigned char *stack, 560457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique struct arg_state *state) 561457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique{ 562457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique unsigned elems = element_count (ty); 563457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique if (available_v (state) < elems) 564457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 565457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique /* There are insufficient V registers. Further V register allocations 566457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique are prevented, the NSAA is adjusted (by allocate_to_stack ()) 567457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique and the argument is copied to memory at the adjusted NSAA. */ 568457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique state->nsrn = N_V_ARG_REG; 569457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique memcpy (allocate_to_stack (state, stack, ty->alignment, ty->size), 570457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique memory, 571457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique ty->size); 572457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 573457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique else 574457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 575457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique int i; 576457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique unsigned short type = get_homogeneous_type (ty); 577457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique for (i = 0; i < elems; i++) 578457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 579457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique void *reg = allocate_to_v (context, state); 580457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique copy_basic_type (reg, memory, type); 581457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique memory += get_basic_type_size (type); 582457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 583457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 584457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique} 585457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 586457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique/* Either allocate an appropriate register for the argument type, or if 587457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique none are available, allocate a stack slot and return a pointer 588457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique to the allocated space. */ 589457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 590457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquestatic void * 591457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piqueallocate_to_register_or_stack (struct call_context *context, 592457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique unsigned char *stack, 593457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique struct arg_state *state, 594457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique unsigned short type) 595457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique{ 596457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique size_t alignment = get_basic_type_alignment (type); 597457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique size_t size = alignment; 598457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique switch (type) 599457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 600457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_FLOAT: 601457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique /* This is the only case for which the allocated stack size 602457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique should not match the alignment of the type. */ 603457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique size = sizeof (UINT32); 604457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique /* Fall through. */ 605457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_DOUBLE: 606457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique if (state->nsrn < N_V_ARG_REG) 607457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique return allocate_to_d (context, state); 608457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique state->nsrn = N_V_ARG_REG; 609457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique break; 610457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#if FFI_TYPE_DOUBLE != FFI_TYPE_LONGDOUBLE 611457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_LONGDOUBLE: 612457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique if (state->nsrn < N_V_ARG_REG) 613457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique return allocate_to_v (context, state); 614457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique state->nsrn = N_V_ARG_REG; 615457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique break; 616457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#endif 617457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_UINT8: 618457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_SINT8: 619457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_UINT16: 620457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_SINT16: 621457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_UINT32: 622457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_SINT32: 623457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_INT: 624457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_POINTER: 625457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_UINT64: 626457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_SINT64: 627457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique if (state->ngrn < N_X_ARG_REG) 628457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique return allocate_to_x (context, state); 629457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique state->ngrn = N_X_ARG_REG; 630457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique break; 631457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique default: 632457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique FFI_ASSERT (0); 633457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 634457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 635457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique return allocate_to_stack (state, stack, alignment, size); 636457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique} 637457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 638457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique/* Copy a value to an appropriate register, or if none are 639457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique available, to the stack. */ 640457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 641457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquestatic void 642457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquecopy_to_register_or_stack (struct call_context *context, 643457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique unsigned char *stack, 644457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique struct arg_state *state, 645457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique void *value, 646457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique unsigned short type) 647457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique{ 648457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique copy_basic_type ( 649457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique allocate_to_register_or_stack (context, stack, state, type), 650457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique value, 651457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique type); 652457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique} 653457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 654457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique/* Marshall the arguments from FFI representation to procedure call 655457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique context and stack. */ 656457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 657457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquestatic unsigned 658457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piqueaarch64_prep_args (struct call_context *context, unsigned char *stack, 659457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique extended_cif *ecif) 660457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique{ 661457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique int i; 662457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique struct arg_state state; 663457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 664457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique arg_init (&state, ALIGN(ecif->cif->bytes, 16)); 665457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 666457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique for (i = 0; i < ecif->cif->nargs; i++) 667457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 668457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique ffi_type *ty = ecif->cif->arg_types[i]; 669457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique switch (ty->type) 670457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 671457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_VOID: 672457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique FFI_ASSERT (0); 673457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique break; 674457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 675457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique /* If the argument is a basic type the argument is allocated to an 676457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique appropriate register, or if none are available, to the stack. */ 677457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_FLOAT: 678457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_DOUBLE: 679457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#if FFI_TYPE_DOUBLE != FFI_TYPE_LONGDOUBLE 680457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_LONGDOUBLE: 681457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#endif 682457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_UINT8: 683457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_SINT8: 684457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_UINT16: 685457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_SINT16: 686457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_UINT32: 687457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_INT: 688457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_SINT32: 689457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_POINTER: 690457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_UINT64: 691457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_SINT64: 692457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique copy_to_register_or_stack (context, stack, &state, 693457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique ecif->avalue[i], ty->type); 694457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique break; 695457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 696457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_STRUCT: 697457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique if (is_hfa (ty)) 698457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 699457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique copy_hfa_to_reg_or_stack (ecif->avalue[i], ty, context, 700457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique stack, &state); 701457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 702457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique else if (ty->size > 16) 703457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 704457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique /* If the argument is a composite type that is larger than 16 705457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique bytes, then the argument has been copied to memory, and 706457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique the argument is replaced by a pointer to the copy. */ 707457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 708457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique copy_to_register_or_stack (context, stack, &state, 709457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique &(ecif->avalue[i]), FFI_TYPE_POINTER); 710457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 711457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique else if (available_x (&state) >= (ty->size + 7) / 8) 712457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 713457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique /* If the argument is a composite type and the size in 714457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique double-words is not more than the number of available 715457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique X registers, then the argument is copied into consecutive 716457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique X registers. */ 717457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique int j; 718457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique for (j = 0; j < (ty->size + 7) / 8; j++) 719457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 720457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique memcpy (allocate_to_x (context, &state), 721457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique &(((UINT64 *) ecif->avalue[i])[j]), 722457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique sizeof (UINT64)); 723457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 724457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 725457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique else 726457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 727457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique /* Otherwise, there are insufficient X registers. Further X 728457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique register allocations are prevented, the NSAA is adjusted 729457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique (by allocate_to_stack ()) and the argument is copied to 730457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique memory at the adjusted NSAA. */ 731457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique state.ngrn = N_X_ARG_REG; 732457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 733457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique memcpy (allocate_to_stack (&state, stack, ty->alignment, 734457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique ty->size), ecif->avalue + i, ty->size); 735457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 736457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique break; 737457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 738457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique default: 739457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique FFI_ASSERT (0); 740457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique break; 741457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 742457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 743457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#if defined (__APPLE__) 744457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique if (i + 1 == ecif->cif->aarch64_nfixedargs) 745457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 746457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique state.ngrn = N_X_ARG_REG; 747457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique state.nsrn = N_V_ARG_REG; 748457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 749457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique state.allocating_variadic = 1; 750457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 751457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#endif 752457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 753457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 754457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique return ecif->cif->aarch64_flags; 755457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique} 756457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 757457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piqueffi_status 758457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piqueffi_prep_cif_machdep (ffi_cif *cif) 759457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique{ 760457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique /* Round the stack up to a multiple of the stack alignment requirement. */ 761457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique cif->bytes = 762457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique (cif->bytes + (AARCH64_STACK_ALIGN - 1)) & ~ (AARCH64_STACK_ALIGN - 1); 763457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 764457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique /* Initialize our flags. We are interested if this CIF will touch a 765457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique vector register, if so we will enable context save and load to 766457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique those registers, otherwise not. This is intended to be friendly 767457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique to lazy float context switching in the kernel. */ 768457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique cif->aarch64_flags = 0; 769457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 770457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique if (is_v_register_candidate (cif->rtype)) 771457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 772457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique cif->aarch64_flags |= AARCH64_FFI_WITH_V; 773457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 774457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique else 775457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 776457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique int i; 777457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique for (i = 0; i < cif->nargs; i++) 778457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique if (is_v_register_candidate (cif->arg_types[i])) 779457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 780457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique cif->aarch64_flags |= AARCH64_FFI_WITH_V; 781457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique break; 782457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 783457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 784457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 785457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#if defined (__APPLE__) 786457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique cif->aarch64_nfixedargs = 0; 787457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#endif 788457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 789457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique return FFI_OK; 790457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique} 791457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 792457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#if defined (__APPLE__) 793457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 794457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique/* Perform Apple-specific cif processing for variadic calls */ 795457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piqueffi_status ffi_prep_cif_machdep_var(ffi_cif *cif, 796457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique unsigned int nfixedargs, 797457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique unsigned int ntotalargs) 798457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique{ 799457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique ffi_status status; 800457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 801457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique status = ffi_prep_cif_machdep (cif); 802457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 803457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique cif->aarch64_nfixedargs = nfixedargs; 804457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 805457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique return status; 806457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique} 807457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 808457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#endif 809457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 810457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique/* Call a function with the provided arguments and capture the return 811457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique value. */ 812457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquevoid 813457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piqueffi_call (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) 814457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique{ 815457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique extended_cif ecif; 816457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 817457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique ecif.cif = cif; 818457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique ecif.avalue = avalue; 819457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique ecif.rvalue = rvalue; 820457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 821457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique switch (cif->abi) 822457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 823457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_SYSV: 824457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 825457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique struct call_context context; 826457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique size_t stack_bytes; 827457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 828457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique /* Figure out the total amount of stack space we need, the 829457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique above call frame space needs to be 16 bytes aligned to 830457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique ensure correct alignment of the first object inserted in 831457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique that space hence the ALIGN applied to cif->bytes.*/ 832457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique stack_bytes = ALIGN(cif->bytes, 16); 833457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 834457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique memset (&context, 0, sizeof (context)); 835457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique if (is_register_candidate (cif->rtype)) 836457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 837457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique ffi_call_SYSV (aarch64_prep_args, &context, &ecif, stack_bytes, fn); 838457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique switch (cif->rtype->type) 839457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 840457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_VOID: 841457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_FLOAT: 842457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_DOUBLE: 843457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#if FFI_TYPE_DOUBLE != FFI_TYPE_LONGDOUBLE 844457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_LONGDOUBLE: 845457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#endif 846457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_UINT8: 847457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_SINT8: 848457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_UINT16: 849457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_SINT16: 850457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_UINT32: 851457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_SINT32: 852457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_POINTER: 853457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_UINT64: 854457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_INT: 855457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_SINT64: 856457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 857457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique void *addr = get_basic_type_addr (cif->rtype->type, 858457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique &context, 0); 859457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique copy_basic_type (rvalue, addr, cif->rtype->type); 860457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique break; 861457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 862457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 863457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_STRUCT: 864457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique if (is_hfa (cif->rtype)) 865457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 866457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique int j; 867457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique unsigned short type = get_homogeneous_type (cif->rtype); 868457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique unsigned elems = element_count (cif->rtype); 869457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique for (j = 0; j < elems; j++) 870457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 871457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique void *reg = get_basic_type_addr (type, &context, j); 872457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique copy_basic_type (rvalue, reg, type); 873457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique rvalue += get_basic_type_size (type); 874457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 875457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 876457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique else if ((cif->rtype->size + 7) / 8 < N_X_ARG_REG) 877457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 878457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique size_t size = ALIGN (cif->rtype->size, sizeof (UINT64)); 879457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique memcpy (rvalue, get_x_addr (&context, 0), size); 880457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 881457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique else 882457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 883457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique FFI_ASSERT (0); 884457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 885457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique break; 886457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 887457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique default: 888457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique FFI_ASSERT (0); 889457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique break; 890457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 891457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 892457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique else 893457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 894457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique memcpy (get_x_addr (&context, 8), &rvalue, sizeof (UINT64)); 895457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique ffi_call_SYSV (aarch64_prep_args, &context, &ecif, 896457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique stack_bytes, fn); 897457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 898457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique break; 899457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 900457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 901457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique default: 902457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique FFI_ASSERT (0); 903457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique break; 904457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 905457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique} 906457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 907457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquestatic unsigned char trampoline [] = 908457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique{ 0x70, 0x00, 0x00, 0x58, /* ldr x16, 1f */ 909457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 0x91, 0x00, 0x00, 0x10, /* adr x17, 2f */ 910457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 0x00, 0x02, 0x1f, 0xd6 /* br x16 */ 911457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique}; 912457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 913457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique/* Build a trampoline. */ 914457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 915457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX,FLAGS) \ 916457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique ({unsigned char *__tramp = (unsigned char*)(TRAMP); \ 917457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique UINT64 __fun = (UINT64)(FUN); \ 918457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique UINT64 __ctx = (UINT64)(CTX); \ 919457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique UINT64 __flags = (UINT64)(FLAGS); \ 920457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique memcpy (__tramp, trampoline, sizeof (trampoline)); \ 921457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique memcpy (__tramp + 12, &__fun, sizeof (__fun)); \ 922457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique memcpy (__tramp + 20, &__ctx, sizeof (__ctx)); \ 923457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique memcpy (__tramp + 28, &__flags, sizeof (__flags)); \ 924457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique ffi_clear_cache(__tramp, __tramp + FFI_TRAMPOLINE_SIZE); \ 925457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique }) 926457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 927457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piqueffi_status 928457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piqueffi_prep_closure_loc (ffi_closure* closure, 929457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique ffi_cif* cif, 930457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique void (*fun)(ffi_cif*,void*,void**,void*), 931457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique void *user_data, 932457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique void *codeloc) 933457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique{ 934457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique if (cif->abi != FFI_SYSV) 935457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique return FFI_BAD_ABI; 936457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 937457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique FFI_INIT_TRAMPOLINE (&closure->tramp[0], &ffi_closure_SYSV, codeloc, 938457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique cif->aarch64_flags); 939457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 940457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique closure->cif = cif; 941457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique closure->user_data = user_data; 942457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique closure->fun = fun; 943457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 944457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique return FFI_OK; 945457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique} 946457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 947457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique/* Primary handler to setup and invoke a function within a closure. 948457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 949457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique A closure when invoked enters via the assembler wrapper 950457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique ffi_closure_SYSV(). The wrapper allocates a call context on the 951457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique stack, saves the interesting registers (from the perspective of 952457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique the calling convention) into the context then passes control to 953457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique ffi_closure_SYSV_inner() passing the saved context and a pointer to 954457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique the stack at the point ffi_closure_SYSV() was invoked. 955457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 956457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique On the return path the assembler wrapper will reload call context 957457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique registers. 958457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 959457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique ffi_closure_SYSV_inner() marshalls the call context into ffi value 960457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique descriptors, invokes the wrapped function, then marshalls the return 961457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique value back into the call context. */ 962457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 963457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquevoid FFI_HIDDEN 964457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piqueffi_closure_SYSV_inner (ffi_closure *closure, struct call_context *context, 965457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique void *stack) 966457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique{ 967457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique ffi_cif *cif = closure->cif; 968457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique void **avalue = (void**) alloca (cif->nargs * sizeof (void*)); 969457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique void *rvalue = NULL; 970457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique int i; 971457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique struct arg_state state; 972457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 973457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique arg_init (&state, ALIGN(cif->bytes, 16)); 974457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 975457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique for (i = 0; i < cif->nargs; i++) 976457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 977457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique ffi_type *ty = cif->arg_types[i]; 978457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 979457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique switch (ty->type) 980457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 981457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_VOID: 982457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique FFI_ASSERT (0); 983457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique break; 984457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 985457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_UINT8: 986457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_SINT8: 987457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_UINT16: 988457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_SINT16: 989457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_UINT32: 990457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_SINT32: 991457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_INT: 992457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_POINTER: 993457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_UINT64: 994457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_SINT64: 995457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_FLOAT: 996457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_DOUBLE: 997457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#if FFI_TYPE_DOUBLE != FFI_TYPE_LONGDOUBLE 998457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_LONGDOUBLE: 999457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique avalue[i] = allocate_to_register_or_stack (context, stack, 1000457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique &state, ty->type); 1001457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique break; 1002457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#endif 1003457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 1004457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_STRUCT: 1005457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique if (is_hfa (ty)) 1006457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 1007457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique unsigned n = element_count (ty); 1008457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique if (available_v (&state) < n) 1009457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 1010457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique state.nsrn = N_V_ARG_REG; 1011457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique avalue[i] = allocate_to_stack (&state, stack, ty->alignment, 1012457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique ty->size); 1013457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 1014457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique else 1015457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 1016457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique switch (get_homogeneous_type (ty)) 1017457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 1018457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_FLOAT: 1019457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 1020457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique /* Eeek! We need a pointer to the structure, 1021457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique however the homogeneous float elements are 1022457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique being passed in individual S registers, 1023457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique therefore the structure is not represented as 1024457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique a contiguous sequence of bytes in our saved 1025457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique register context. We need to fake up a copy 1026457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique of the structure laid out in memory 1027457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique correctly. The fake can be tossed once the 1028457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique closure function has returned hence alloca() 1029457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique is sufficient. */ 1030457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique int j; 1031457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique UINT32 *p = avalue[i] = alloca (ty->size); 1032457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique for (j = 0; j < element_count (ty); j++) 1033457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique memcpy (&p[j], 1034457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique allocate_to_s (context, &state), 1035457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique sizeof (*p)); 1036457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique break; 1037457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 1038457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 1039457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_DOUBLE: 1040457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 1041457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique /* Eeek! We need a pointer to the structure, 1042457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique however the homogeneous float elements are 1043457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique being passed in individual S registers, 1044457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique therefore the structure is not represented as 1045457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique a contiguous sequence of bytes in our saved 1046457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique register context. We need to fake up a copy 1047457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique of the structure laid out in memory 1048457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique correctly. The fake can be tossed once the 1049457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique closure function has returned hence alloca() 1050457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique is sufficient. */ 1051457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique int j; 1052457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique UINT64 *p = avalue[i] = alloca (ty->size); 1053457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique for (j = 0; j < element_count (ty); j++) 1054457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique memcpy (&p[j], 1055457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique allocate_to_d (context, &state), 1056457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique sizeof (*p)); 1057457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique break; 1058457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 1059457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 1060457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#if FFI_TYPE_DOUBLE != FFI_TYPE_LONGDOUBLE 1061457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_LONGDOUBLE: 1062457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique memcpy (&avalue[i], 1063457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique allocate_to_v (context, &state), 1064457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique sizeof (*avalue)); 1065457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique break; 1066457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#endif 1067457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 1068457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique default: 1069457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique FFI_ASSERT (0); 1070457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique break; 1071457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 1072457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 1073457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 1074457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique else if (ty->size > 16) 1075457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 1076457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique /* Replace Composite type of size greater than 16 with a 1077457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique pointer. */ 1078457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique memcpy (&avalue[i], 1079457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique allocate_to_register_or_stack (context, stack, 1080457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique &state, FFI_TYPE_POINTER), 1081457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique sizeof (avalue[i])); 1082457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 1083457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique else if (available_x (&state) >= (ty->size + 7) / 8) 1084457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 1085457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique avalue[i] = get_x_addr (context, state.ngrn); 1086457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique state.ngrn += (ty->size + 7) / 8; 1087457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 1088457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique else 1089457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 1090457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique state.ngrn = N_X_ARG_REG; 1091457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 1092457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique avalue[i] = allocate_to_stack (&state, stack, ty->alignment, 1093457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique ty->size); 1094457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 1095457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique break; 1096457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 1097457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique default: 1098457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique FFI_ASSERT (0); 1099457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique break; 1100457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 1101457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 1102457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 1103457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique /* Figure out where the return value will be passed, either in 1104457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique registers or in a memory block allocated by the caller and passed 1105457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique in x8. */ 1106457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 1107457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique if (is_register_candidate (cif->rtype)) 1108457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 1109457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique /* Register candidates are *always* returned in registers. */ 1110457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 1111457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique /* Allocate a scratchpad for the return value, we will let the 1112457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique callee scrible the result into the scratch pad then move the 1113457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique contents into the appropriate return value location for the 1114457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique call convention. */ 1115457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique rvalue = alloca (cif->rtype->size); 1116457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique (closure->fun) (cif, rvalue, avalue, closure->user_data); 1117457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 1118457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique /* Copy the return value into the call context so that it is returned 1119457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique as expected to our caller. */ 1120457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique switch (cif->rtype->type) 1121457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 1122457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_VOID: 1123457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique break; 1124457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 1125457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_UINT8: 1126457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_UINT16: 1127457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_UINT32: 1128457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_POINTER: 1129457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_UINT64: 1130457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_SINT8: 1131457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_SINT16: 1132457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_INT: 1133457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_SINT32: 1134457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_SINT64: 1135457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_FLOAT: 1136457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_DOUBLE: 1137457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#if FFI_TYPE_DOUBLE != FFI_TYPE_LONGDOUBLE 1138457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_LONGDOUBLE: 1139457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#endif 1140457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 1141457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique void *addr = get_basic_type_addr (cif->rtype->type, context, 0); 1142457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique copy_basic_type (addr, rvalue, cif->rtype->type); 1143457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique break; 1144457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 1145457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_STRUCT: 1146457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique if (is_hfa (cif->rtype)) 1147457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 1148457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique int j; 1149457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique unsigned short type = get_homogeneous_type (cif->rtype); 1150457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique unsigned elems = element_count (cif->rtype); 1151457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique for (j = 0; j < elems; j++) 1152457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 1153457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique void *reg = get_basic_type_addr (type, context, j); 1154457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique copy_basic_type (reg, rvalue, type); 1155457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique rvalue += get_basic_type_size (type); 1156457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 1157457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 1158457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique else if ((cif->rtype->size + 7) / 8 < N_X_ARG_REG) 1159457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 1160457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique size_t size = ALIGN (cif->rtype->size, sizeof (UINT64)) ; 1161457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique memcpy (get_x_addr (context, 0), rvalue, size); 1162457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 1163457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique else 1164457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 1165457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique FFI_ASSERT (0); 1166457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 1167457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique break; 1168457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique default: 1169457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique FFI_ASSERT (0); 1170457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique break; 1171457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 1172457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 1173457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique else 1174457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 1175457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique memcpy (&rvalue, get_x_addr (context, 8), sizeof (UINT64)); 1176457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique (closure->fun) (cif, rvalue, avalue, closure->user_data); 1177457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 1178457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique} 1179457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 1180