1a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* ----------------------------------------------------------------------- 2a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project ffi.c - Copyright (c) 1998 Cygnus Solutions 3a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project Copyright (c) 2004 Simon Posnjak 4a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project Copyright (c) 2005 Axis Communications AB 5a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project Copyright (C) 2007 Free Software Foundation, Inc. 6a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 7a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project CRIS Foreign Function Interface 8a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 9a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project Permission is hereby granted, free of charge, to any person obtaining 10a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project a copy of this software and associated documentation files (the 11a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project ``Software''), to deal in the Software without restriction, including 12a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project without limitation the rights to use, copy, modify, merge, publish, 13a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project distribute, sublicense, and/or sell copies of the Software, and to 14a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project permit persons to whom the Software is furnished to do so, subject to 15a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project the following conditions: 16a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 17a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project The above copyright notice and this permission notice shall be included 18a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project in all copies or substantial portions of the Software. 19a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 20a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS 21a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 22a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 23a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project IN NO EVENT SHALL SIMON POSNJAK BE LIABLE FOR ANY CLAIM, DAMAGES OR 24a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 25a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 26a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project OTHER DEALINGS IN THE SOFTWARE. 27a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project ----------------------------------------------------------------------- */ 28a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 29a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#include <ffi.h> 30a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#include <ffi_common.h> 31a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 32a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#define STACK_ARG_SIZE(x) ALIGN(x, FFI_SIZEOF_ARG) 33a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 34a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectstatic ffi_status 35a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectinitialize_aggregate_packed_struct (ffi_type * arg) 36a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{ 37a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project ffi_type **ptr; 38a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 39a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project FFI_ASSERT (arg != NULL); 40a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 41a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project FFI_ASSERT (arg->elements != NULL); 42a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project FFI_ASSERT (arg->size == 0); 43a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project FFI_ASSERT (arg->alignment == 0); 44a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 45a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project ptr = &(arg->elements[0]); 46a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 47a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project while ((*ptr) != NULL) 48a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 49a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if (((*ptr)->size == 0) 50a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project && (initialize_aggregate_packed_struct ((*ptr)) != FFI_OK)) 51a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project return FFI_BAD_TYPEDEF; 52a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 53a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project FFI_ASSERT (ffi_type_test ((*ptr))); 54a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 55a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project arg->size += (*ptr)->size; 56a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 57a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project arg->alignment = (arg->alignment > (*ptr)->alignment) ? 58a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project arg->alignment : (*ptr)->alignment; 59a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 60a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project ptr++; 61a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 62a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 63a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if (arg->size == 0) 64a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project return FFI_BAD_TYPEDEF; 65a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project else 66a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project return FFI_OK; 67a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project} 68a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 69a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectint 70a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectffi_prep_args (char *stack, extended_cif * ecif) 71a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{ 72a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project unsigned int i; 73a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project unsigned int struct_count = 0; 74a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project void **p_argv; 75a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project char *argp; 76a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project ffi_type **p_arg; 77a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 78a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project argp = stack; 79a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 80a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project p_argv = ecif->avalue; 81a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 82a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types; 83a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project (i != 0); i--, p_arg++) 84a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 85a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project size_t z; 86a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 87a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project switch ((*p_arg)->type) 88a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 89a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_STRUCT: 90a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 91a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project z = (*p_arg)->size; 92a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if (z <= 4) 93a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 94a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project memcpy (argp, *p_argv, z); 95a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project z = 4; 96a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 97a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project else if (z <= 8) 98a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 99a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project memcpy (argp, *p_argv, z); 100a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project z = 8; 101a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 102a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project else 103a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 104a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project unsigned int uiLocOnStack; 105a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project z = sizeof (void *); 106a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project uiLocOnStack = 4 * ecif->cif->nargs + struct_count; 107a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project struct_count = struct_count + (*p_arg)->size; 108a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project *(unsigned int *) argp = 109a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project (unsigned int) (UINT32 *) (stack + uiLocOnStack); 110a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project memcpy ((stack + uiLocOnStack), *p_argv, (*p_arg)->size); 111a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 112a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 113a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 114a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project default: 115a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project z = (*p_arg)->size; 116a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if (z < sizeof (int)) 117a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 118a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project switch ((*p_arg)->type) 119a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 120a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_SINT8: 121a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project *(signed int *) argp = (signed int) *(SINT8 *) (*p_argv); 122a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 123a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 124a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_UINT8: 125a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project *(unsigned int *) argp = 126a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project (unsigned int) *(UINT8 *) (*p_argv); 127a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 128a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 129a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_SINT16: 130a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project *(signed int *) argp = (signed int) *(SINT16 *) (*p_argv); 131a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 132a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 133a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_UINT16: 134a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project *(unsigned int *) argp = 135a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project (unsigned int) *(UINT16 *) (*p_argv); 136a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 137a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 138a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project default: 139a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project FFI_ASSERT (0); 140a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 141a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project z = sizeof (int); 142a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 143a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project else if (z == sizeof (int)) 144a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project *(unsigned int *) argp = (unsigned int) *(UINT32 *) (*p_argv); 145a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project else 146a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project memcpy (argp, *p_argv, z); 147a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 148a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 149a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project p_argv++; 150a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project argp += z; 151a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 152a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 153a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project return (struct_count); 154a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project} 155a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 156a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectffi_status 157a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectffi_prep_cif (ffi_cif * cif, 158a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project ffi_abi abi, unsigned int nargs, 159a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project ffi_type * rtype, ffi_type ** atypes) 160a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{ 161a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project unsigned bytes = 0; 162a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project unsigned int i; 163a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project ffi_type **ptr; 164a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 165a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project FFI_ASSERT (cif != NULL); 166a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project FFI_ASSERT ((abi > FFI_FIRST_ABI) && (abi <= FFI_DEFAULT_ABI)); 167a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 168a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project cif->abi = abi; 169a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project cif->arg_types = atypes; 170a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project cif->nargs = nargs; 171a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project cif->rtype = rtype; 172a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 173a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project cif->flags = 0; 174a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 175a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if ((cif->rtype->size == 0) 176a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project && (initialize_aggregate_packed_struct (cif->rtype) != FFI_OK)) 177a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project return FFI_BAD_TYPEDEF; 178a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 179a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project FFI_ASSERT_VALID_TYPE (cif->rtype); 180a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 181a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++) 182a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 183a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if (((*ptr)->size == 0) 184a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project && (initialize_aggregate_packed_struct ((*ptr)) != FFI_OK)) 185a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project return FFI_BAD_TYPEDEF; 186a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 187a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project FFI_ASSERT_VALID_TYPE (*ptr); 188a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 189a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if (((*ptr)->alignment - 1) & bytes) 190a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project bytes = ALIGN (bytes, (*ptr)->alignment); 191a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if ((*ptr)->type == FFI_TYPE_STRUCT) 192a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 193a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if ((*ptr)->size > 8) 194a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 195a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project bytes += (*ptr)->size; 196a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project bytes += sizeof (void *); 197a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 198a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project else 199a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 200a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if ((*ptr)->size > 4) 201a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project bytes += 8; 202a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project else 203a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project bytes += 4; 204a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 205a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 206a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project else 207a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project bytes += STACK_ARG_SIZE ((*ptr)->size); 208a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 209a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 210a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project cif->bytes = bytes; 211a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 212a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project return ffi_prep_cif_machdep (cif); 213a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project} 214a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 215a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectffi_status 216a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectffi_prep_cif_machdep (ffi_cif * cif) 217a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{ 218a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project switch (cif->rtype->type) 219a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 220a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_VOID: 221a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_STRUCT: 222a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_FLOAT: 223a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_DOUBLE: 224a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_SINT64: 225a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_UINT64: 226a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project cif->flags = (unsigned) cif->rtype->type; 227a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 228a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 229a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project default: 230a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project cif->flags = FFI_TYPE_INT; 231a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 232a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 233a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 234a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project return FFI_OK; 235a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project} 236a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 237a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectextern void ffi_call_SYSV (int (*)(char *, extended_cif *), 238a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project extended_cif *, 239a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project unsigned, unsigned, unsigned *, void (*fn) ()) 240a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project __attribute__ ((__visibility__ ("hidden"))); 241a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 242a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectvoid 243a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectffi_call (ffi_cif * cif, void (*fn) (), void *rvalue, void **avalue) 244a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{ 245a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project extended_cif ecif; 246a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 247a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project ecif.cif = cif; 248a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project ecif.avalue = avalue; 249a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 250a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if ((rvalue == NULL) && (cif->rtype->type == FFI_TYPE_STRUCT)) 251a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 252a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project ecif.rvalue = alloca (cif->rtype->size); 253a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 254a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project else 255a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project ecif.rvalue = rvalue; 256a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 257a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project switch (cif->abi) 258a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 259a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_SYSV: 260a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project ffi_call_SYSV (ffi_prep_args, &ecif, cif->bytes, 261a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project cif->flags, ecif.rvalue, fn); 262a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 263a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project default: 264a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project FFI_ASSERT (0); 265a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 266a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 267a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project} 268a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 269a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* Because the following variables are not exported outside libffi, we 270a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project mark them hidden. */ 271a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 272a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* Assembly code for the jump stub. */ 273a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectextern const char ffi_cris_trampoline_template[] 274a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project __attribute__ ((__visibility__ ("hidden"))); 275a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 276a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* Offset into ffi_cris_trampoline_template of where to put the 277a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project ffi_prep_closure_inner function. */ 278a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectextern const int ffi_cris_trampoline_fn_offset 279a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project __attribute__ ((__visibility__ ("hidden"))); 280a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 281a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* Offset into ffi_cris_trampoline_template of where to put the 282a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project closure data. */ 283a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectextern const int ffi_cris_trampoline_closure_offset 284a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project __attribute__ ((__visibility__ ("hidden"))); 285a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 286a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* This function is sibling-called (jumped to) by the closure 287a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project trampoline. We get R10..R13 at PARAMS[0..3] and a copy of [SP] at 288a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project PARAMS[4] to simplify handling of a straddling parameter. A copy 289a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project of R9 is at PARAMS[5] and SP at PARAMS[6]. These parameters are 290a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project put at the appropriate place in CLOSURE which is then executed and 291a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project the return value is passed back to the caller. */ 292a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 293a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectstatic unsigned long long 294a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectffi_prep_closure_inner (void **params, ffi_closure* closure) 295a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{ 296a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project char *register_args = (char *) params; 297a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project void *struct_ret = params[5]; 298a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project char *stack_args = params[6]; 299a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project char *ptr = register_args; 300a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project ffi_cif *cif = closure->cif; 301a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project ffi_type **arg_types = cif->arg_types; 302a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 303a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project /* Max room needed is number of arguments as 64-bit values. */ 304a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project void **avalue = alloca (closure->cif->nargs * sizeof(void *)); 305a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project int i; 306a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project int doing_regs; 307a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project long long llret = 0; 308a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 309a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project /* Find the address of each argument. */ 310a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project for (i = 0, doing_regs = 1; i < cif->nargs; i++) 311a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 312a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project /* Types up to and including 8 bytes go by-value. */ 313a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if (arg_types[i]->size <= 4) 314a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 315a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project avalue[i] = ptr; 316a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project ptr += 4; 317a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 318a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project else if (arg_types[i]->size <= 8) 319a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 320a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project avalue[i] = ptr; 321a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project ptr += 8; 322a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 323a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project else 324a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 325a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project FFI_ASSERT (arg_types[i]->type == FFI_TYPE_STRUCT); 326a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 327a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project /* Passed by-reference, so copy the pointer. */ 328a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project avalue[i] = *(void **) ptr; 329a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project ptr += 4; 330a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 331a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 332a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project /* If we've handled more arguments than fit in registers, start 333a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project looking at the those passed on the stack. Step over the 334a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project first one if we had a straddling parameter. */ 335a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if (doing_regs && ptr >= register_args + 4*4) 336a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 337a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project ptr = stack_args + ((ptr > register_args + 4*4) ? 4 : 0); 338a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project doing_regs = 0; 339a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 340a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 341a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 342a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project /* Invoke the closure. */ 343a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project (closure->fun) (cif, 344a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 345a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project cif->rtype->type == FFI_TYPE_STRUCT 346a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project /* The caller allocated space for the return 347a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project structure, and passed a pointer to this space in 348a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project R9. */ 349a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project ? struct_ret 350a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 351a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project /* We take advantage of being able to ignore that 352a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project the high part isn't set if the return value is 353a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project not in R10:R11, but in R10 only. */ 354a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project : (void *) &llret, 355a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 356a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project avalue, closure->user_data); 357a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 358a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project return llret; 359a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project} 360a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 361a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* API function: Prepare the trampoline. */ 362a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 363a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectffi_status 364a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectffi_prep_closure_loc (ffi_closure* closure, 365a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project ffi_cif* cif, 366a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project void (*fun)(ffi_cif *, void *, void **, void*), 367a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project void *user_data, 368a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project void *codeloc) 369a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{ 370a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project void *innerfn = ffi_prep_closure_inner; 371a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project FFI_ASSERT (cif->abi == FFI_SYSV); 372a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project closure->cif = cif; 373a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project closure->user_data = user_data; 374a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project closure->fun = fun; 375a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project memcpy (closure->tramp, ffi_cris_trampoline_template, 376a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project FFI_CRIS_TRAMPOLINE_CODE_PART_SIZE); 377a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project memcpy (closure->tramp + ffi_cris_trampoline_fn_offset, 378a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project &innerfn, sizeof (void *)); 379a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project memcpy (closure->tramp + ffi_cris_trampoline_closure_offset, 380a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project &codeloc, sizeof (void *)); 381a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 382a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project return FFI_OK; 383a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project} 384